package com.zmn.oms.business.impl.work;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWork;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWorkDiscount;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWorkReview;
import com.zmn.common.constant.FicoConsts;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.oms.business.impl.base.AbstractListEsQueryServiceImpl;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.business.interfaces.work.OrderWorkListBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.dro.normal.order.OrderRelationDRO;
import com.zmn.oms.common.dro.normal.order.WorkRelationDRO;
import com.zmn.oms.model.entity.order.NonClaimOrder;
import com.zmn.oms.model.entity.work.OrderBaseEsQuery;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkQuery;
import com.zmn.oms.services.interfaces.order.NonClaimOrderService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.uuc.common.dro.user.UserBaseDRO;
import com.zmn.uuc.common.dro.user.UserDetailDRO;
import com.zmn.uuc.dubbo.interfaces.user.UserListRemoteService;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.hbase.thirdparty.com.google.common.collect.Streams;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.metrics.ParsedSum;
import org.elasticsearch.search.aggregations.metrics.SumAggregationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.SourceFilter;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 类描述：工单列表查询
 *
 * @author lujia
 * @date 2018/11/29 14:13
 */
@Service
public class OrderWorkListBServiceImpl extends AbstractListEsQueryServiceImpl implements OrderWorkListBService {

    private static final Logger logger = LoggerFactory.getLogger(OrderWorkListBServiceImpl.class);

    @Autowired
    private OrderWorkEsBService orderWorkEsBService;
    @Autowired
    private NonClaimOrderService nonClaimOrderService;
    @Autowired
    private OrderWorkService orderWorkService;

    @Reference(version = com.zmn.uuc.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private UserListRemoteService userListRemoteService;

    @Override
    public NativeSearchQuery getSearchQueryByQuery(OrderBaseEsQuery query) {
        if (Objects.equals(GlobalConsts.YES, query.getNoneQuery())) {
            return null;
        }
        return super.builderSearchQuery(query);
    }

    @Override
    public OrderRelationDRO getOrderRelationByOrderIdAndWorkId(Long orderId, Long workId) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 非新单查询源单信息和源单的关联工单
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            boolQueryBuilder.should(QueryBuilders.termQuery("id", orderWork.getOriginalId()));
            boolQueryBuilder.should(QueryBuilders.termQuery("originalId", orderWork.getOriginalId()));
        } else {
            boolQueryBuilder.should(QueryBuilders.termQuery("originalId", orderId));
        }

        NativeSearchQuery searchQuery = new NativeSearchQuery(boolQueryBuilder);
        searchQuery.setPageable(PageRequest.of(0, 50));
        String[] columns = {"id", "type", "originalId", "orderId", "inputTime", "productList.showProductName", "totalAmount", "channelName", "statusName", "resultStatusName", "workReviewList", "lastRefundAmountTime"};
        SourceFilter sourceFilter = new FetchSourceFilter(columns, null);
        searchQuery.addSourceFilter(sourceFilter);
        List<EsOrderWork> esOrderWorks = orderWorkEsBService.listPageByQuery(searchQuery);

        OrderRelationDRO orderRelationDRO = new OrderRelationDRO();
        List<WorkRelationDRO> reworkList = Lists.newArrayListWithCapacity(esOrderWorks.size());
        List<WorkRelationDRO> refundList = Lists.newArrayListWithCapacity(esOrderWorks.size());
        List<WorkRelationDRO> compensateList = Lists.newArrayListWithCapacity(esOrderWorks.size());

        esOrderWorks.forEach(esOrderWork -> {
            // 如果找到当前订单的源单信息，则返回源单信息
            if (Objects.equals(orderWork.getOriginalId(), esOrderWork.getId())) {
                orderRelationDRO.setOriginalWork(this.setWorkRelationDRO(esOrderWork));
                return;
            }
            switch (esOrderWork.getType()) {
                case OrderConsts.ORDER_TYPE_REWORK:
                    reworkList.add(this.setWorkRelationDRO(esOrderWork));
                    break;
                case OrderConsts.ORDER_TYPE_REFUND:
                    refundList.add(this.setWorkRelationDRO(esOrderWork));
                    break;
                case OrderConsts.ORDER_TYPE_COMPENSATE:
                    compensateList.add(this.setWorkRelationDRO(esOrderWork));
                    break;
                default:
                    break;
            }
        });

        orderRelationDRO.setReworkList(reworkList);
        orderRelationDRO.setRefundList(refundList);
        orderRelationDRO.setCompensateList(compensateList);
        return orderRelationDRO;
    }

    /**
     * es赋值dro
     * @param esOrderWork
     * @return
     */
    private WorkRelationDRO setWorkRelationDRO(EsOrderWork esOrderWork) {
        WorkRelationDRO workRelationDRO = new WorkRelationDRO();
        workRelationDRO.setOrderId(esOrderWork.getOrderId());
        workRelationDRO.setWorkId(esOrderWork.getId());
        workRelationDRO.setCreateTime(esOrderWork.getInputTime());
        workRelationDRO.setShowProductName(esOrderWork.getProductList().get(0).getShowProductName());
        workRelationDRO.setTotalAmount(esOrderWork.getTotalAmount());
        workRelationDRO.setChannelName(esOrderWork.getChannelName());
        workRelationDRO.setStatusName(esOrderWork.getStatusName());
        workRelationDRO.setResultStatusName(esOrderWork.getResultStatusName());
        workRelationDRO.setRefundAmountTime(esOrderWork.getLastRefundAmountTime());
        List<EsOrderWorkReview> workReviewList = esOrderWork.getWorkReviewList();
        if (CollectionUtil.isNullOrEmpty(workReviewList)) {
            return workRelationDRO;
        }
        // 退款单的审核
        if (Objects.equals(esOrderWork.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
            EsOrderWorkReview review = Streams.findLast(workReviewList.stream().filter(e -> Objects.equals(e.getReviewType(), OrderConsts.OMS_ORDER_REVIEW_REFUND))).orElse(null);
            if (Objects.isNull(review)) {
                return workRelationDRO;
            }
            workRelationDRO.setReviewStatusName(OrderConsts.getOrderWorkReviewStatusName(review.getReviewStatus()));
            return workRelationDRO;
        }
        // 赔偿单的审核
        if (Objects.equals(esOrderWork.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            EsOrderWorkReview review = Streams.findLast(workReviewList.stream().filter(e -> Objects.equals(e.getReviewType(), OrderConsts.OMS_ORDER_REVIEW_COMPENSATE))).orElse(null);
            if (Objects.isNull(review)) {
                return workRelationDRO;
            }
            workRelationDRO.setReviewStatusName(OrderConsts.getOrderWorkReviewStatusName(review.getReviewStatus()));
        }
        return workRelationDRO;
    }

    @Override
    public List<EsOrderWork> listPageOrderWorkBySearchQuery(OrderBaseEsQuery query, NativeSearchQuery searchQuery) {
        // 构建查询对象
        if (searchQuery == null) {
            query.setTotalCount(0);
            return Lists.newArrayList();
        }

        List<EsOrderWork> esOrderWorkList = orderWorkEsBService.listPageByQuery(searchQuery);
        query.setTotalCount(searchQuery.getMaxResults());
        return esOrderWorkList;
    }

    @Override
    public List<EsOrderWork> listPageOrderWorkByQuery(OrderBaseEsQuery query) {
        // 构建查询对象
        NativeSearchQuery searchQuery = this.getSearchQueryByQuery(query);
        return this.listPageOrderWorkBySearchQuery(query, searchQuery);
    }

    /**
     * 查询临时用户订单
     * @param query
     * @return
     */
    @Override
    public List<EsOrderWork> listTempUserOrderWorkByQuery(OrderWorkQuery query) {

        // 根据手机号查询正式用户id
        ResponseDTO<List<UserBaseDRO>> responseDTO = userListRemoteService.listUserByMobile(query.getConcatPhone(), false);
        logger.debug("根据手机号查询用户信息入参：[{}]，出参：[{}]", query.getConcatPhone(), JSON.toJSONString(responseDTO));
        if (!responseDTO.isSuccess()) {
            return Lists.newArrayList();
        }
        List<Long> userIdList = responseDTO.getData().stream().map(UserBaseDRO::getUserId).collect(Collectors.toList());
        query.setNotUserIdList(userIdList);
        // 构建查询对象
        NativeSearchQuery searchQuery = super.builderSearchQuery(query);
        if (searchQuery == null) {
            return Lists.newArrayList();
        }
        List<EsOrderWork> esOrderWorkList = orderWorkEsBService.listPageByQuery(searchQuery);
        logger.debug("ES初选数量：[{}]", esOrderWorkList.size());
        if (CollectionUtil.isNullOrEmpty(esOrderWorkList)) {
            return Lists.newArrayList();
        }

        List<Long> esUserIdList = esOrderWorkList.stream().map(EsOrderWork::getUserId).distinct().collect(Collectors.toList());
        logger.debug("根据用户id查询用户信息入参：[{}]", JSON.toJSONString(esUserIdList));
        ResponseDTO<List<UserDetailDRO>> listResponseDTO = userListRemoteService.listUserDetailByUserIds(esUserIdList, false);
        logger.debug("根据用户id查询用户信息出参：[{}]", JSON.toJSONString(listResponseDTO));
        if (!listResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
            return Lists.newArrayList();
        }
        List<Long> tempUserIdList = listResponseDTO.getData().stream()
                .filter(dro -> dro.getTempFlag() == GlobalConsts.NO)
                .map(UserBaseDRO::getUserId).collect(Collectors.toList());
        logger.debug("临时用户过滤正式用户：[{}]", JSON.toJSONString(tempUserIdList));
        List<EsOrderWork> tempEsOrderList = esOrderWorkList.stream()
                .filter(esOrderWork -> !tempUserIdList.contains(esOrderWork.getUserId())).collect(Collectors.toList());
        logger.debug("临时用户第一次过滤数量：[{}]，订单[{}]", tempEsOrderList.size(), JSON.toJSONString(tempEsOrderList));
        if (CollectionUtil.isNullOrEmpty(tempEsOrderList)) {
            return Lists.newArrayList();
        }
        // 查询不认领订单
        List<Long> orderIdList = tempEsOrderList.stream().map(EsOrderWork::getOrderId).collect(Collectors.toList());
        List<NonClaimOrder> nonClaimOrderList = nonClaimOrderService.listNonClaimOrderByOrderIdList(orderIdList);
        logger.debug("不认领数量：[{}]", nonClaimOrderList.size());
        if (CollectionUtil.isNullOrEmpty(nonClaimOrderList)) {
            return tempEsOrderList;
        }

        // es订单过滤不认领订单
        List<Long> nonClaimOrderIdList = nonClaimOrderList.stream().map(NonClaimOrder::getOrderId)
                .collect(Collectors.toList());
        logger.debug("临时用户不认领订单：[{}]", JSON.toJSONString(nonClaimOrderIdList));
        List<EsOrderWork> resultList = tempEsOrderList.stream()
                .filter(esOrderWork -> !nonClaimOrderIdList.contains(esOrderWork.getOrderId()))
                .collect(Collectors.toList());
        logger.debug("临时用户第二次过滤不认领数量：[{}]，最终订单：[{}]", resultList.size(), JSON.toJSONString(resultList));
        return resultList;
    }

    @Override
    public EsOrderWork findOrderWorkById(Long id) {
        EsOrderWork esOrderWork = orderWorkEsBService.getEsOrderWorkById(id);
        if (esOrderWork == null) {
            logger.error("#oms#order 订单不存在 id : {}", id);
            return null;
        }

        return esOrderWork;
    }

    @Override
    public Integer countOrderWorkByQuery(OrderBaseEsQuery query) {
        NativeSearchQuery searchQuery = super.builderSearchQuery(query);
        if (searchQuery == null) {
            return GlobalConsts.NONE;
        }
        return orderWorkEsBService.countByQuery(searchQuery).intValue();
    }

    @Override
    public Integer countOrderWorkByQuery(NativeSearchQuery searchQuery) {
        return orderWorkEsBService.countByQuery(searchQuery).intValue();
    }

    @Override
    public Integer countMasterByQuery(OrderBaseEsQuery query) {
        query.setPageSize(0);
        NativeSearchQuery searchQuery = (NativeSearchQuery) super.builderSearchQuery(query);
        if (searchQuery == null) {
            return GlobalConsts.NONE;
        }

        SumAggregationBuilder masterNumBuilder = AggregationBuilders
                .sum("masterNum")
                .script(new Script("params._source.masterList == null ? 0 : params._source.masterList.size()"));
        searchQuery.addAggregation(masterNumBuilder);
        Aggregations aggregations = orderWorkEsBService.getAggregationsByQuery(searchQuery);
        Map<String, Aggregation> asMap = aggregations.getAsMap();
        ParsedSum masterNum = (ParsedSum)asMap.get("masterNum");
        return (int)masterNum.getValue();
    }

    @Override
    public Integer getCouponDiscountAmountByOrderIdList(List<Long> orderIdList) {

        if (CollectionUtils.isEmpty(orderIdList) || orderIdList.size() > OrderConsts.MAX_QUERY_ORDER_SIZE) {
            return 0;
        }

        OrderWorkQuery query = new OrderWorkQuery();
        query.setOrderIdList(orderIdList);
        query.setPageSize(OrderConsts.MAX_QUERY_ORDER_SIZE);
        List<EsOrderWork> esOrderWorkList = listPageOrderWorkByQuery(query);

        Integer discountAmount = 0;
        for (EsOrderWork esOrderWork : esOrderWorkList) {
            List<EsOrderWorkDiscount> discountList = esOrderWork.getDiscountList();
            if (!CollectionUtils.isEmpty(discountList)) {
                int sum = discountList.stream().filter(d -> Objects.equals(d.getDiscountCateg(), FicoConsts.ORDER_IN_DISCOUNT_CATEG_COUPON)).mapToInt(value -> value.getDiscountAmount()).sum();
                discountAmount += sum;
            }
        }

        return discountAmount;
    }

    /**
     * 查询订单原单的返修次数，完成才算一次返修
     *
     * @param orderId 原单订单
     * @param workId 原单工单
     * @return
     */
    @Override
    public Integer countReworkSuccessByWorkId(Long orderId, Long workId) {

        OrderWorkQuery query = new OrderWorkQuery();
        query.setOriginalId(workId);
        // 返修
        query.setWorkType(Lists.newArrayList(OrderConsts.ORDER_TYPE_REWORK));
        // 已完成
        query.setWorkStatus(Lists.newArrayList(OrderStatusConsts.WORK_STATUS_COMPLETE,
                OrderStatusConsts.WORK_STATUS_CHECKOUT, OrderStatusConsts.WORK_STATUS_ACCOUNT));

        NativeSearchQuery searchQuery = super.builderSearchQuery(query);
        if (searchQuery == null) {
            return GlobalConsts.NONE;
        }
        return orderWorkEsBService.countByQuery(searchQuery).intValue();
    }


}
